/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/**
 * \file
 * \brief Handling MaCI Service information storage over MaCI::SQL interface.
 * \author Antti Maula <antti.maula@tkk.fi>
 * \author Teppo Pirttioja (DB format design)
 */
#ifndef _MACI_INTERFACE_SQL_EXTENSION_MACISERVICESDB_HPP_
#define _MACI_INTERFACE_SQL_EXTENSION_MACISERVICESDB_HPP_

#include "SQLQuery.hpp"
#include "SQLResult.hpp"
#include "SQLClient.hpp"
#include "SQLResultTypes.hpp"
#include "SQLExtension.hpp"
#include <string>
#include <vector>

namespace MaCI {
  namespace SQL {
    namespace Ext {
      
      /** Single row of MaCIServicesDB type.
       */
      struct SMaCIServicesRow
      {
      public:
        SMaCIServicesRow(void) 
          : id(),
            name(),
            value(),
            seconds(),
            microSeconds(),
            stored(),
            param(),
            server(),
            port(),
            serviceMajor(),
            serviceMinor(),
            clientName() {}

        SMaCIServicesRow(const TSQLRow &aRow)
          : id(),
            name(),
            value(),
            seconds(),
            microSeconds(),
            stored(),
            param(),
            server(),
            port(),
            serviceMajor(),
            serviceMinor(),
            clientName() {
          DecodeSQLResultRow(aRow);
        }
        
        ~SMaCIServicesRow() {
        }
        
        /** This function attempts to decode a SQL Row as type
         * SMaCIServicesRow.
         *
         * This function takes a TSQLRow as parameter, and attempts to
         * decode all fields to current container. This function will
         * fail if 1) the SQLRow size doesn't match required size of
         * 12 fields.  2) if any of the integer type fields doesn't
         * correctly convert to integer.
         *
         * \note This Decoder expects to get ALL available fields. If
         * the query is made so, that result set DOESN'T contain all
         * the available fields (by selecting fields), a special
         * processing function needs to be written. (Or contents be
         * taken care of manually)
         *
         * @param[in] aRow      TSQLRow container to decode as 
         *                      SMaCIServicesRow.
         * @return              'true' if all conditions mentioned 
         *                      above are met, otherwise 'false'.
         */
        bool DecodeSQLResultRow(const TSQLRow &aRow) {
          bool result = false;

          // This is not a magic value, this is the number of fields
          // in row. Very static.
          if (aRow.size() == 12) {
            result = aRow.at(0).ConvertTo(id);
            result &= aRow.at(1).ConvertTo(name);
            result &= aRow.at(2).ConvertTo(value);
            result &= aRow.at(3).ConvertTo(seconds);
            result &= aRow.at(4).ConvertTo(microSeconds);
            result &= aRow.at(5).ConvertTo(stored);
            result &= aRow.at(6).ConvertTo(param);
            result &= aRow.at(7).ConvertTo(server);
            result &= aRow.at(8).ConvertTo(port);

            result &= aRow.at(9).ConvertTo(serviceMajor);
            if (!result) { serviceMajor = 0; result = true; }

            result &= aRow.at(10).ConvertTo(serviceMinor);
            if (!result) { serviceMinor = 0; result = true; }            

            result &= aRow.at(11).ConvertTo(clientName);

          }
          return result;
        }

      public:
        unsigned int id;
        std::string name;
        unsigned int value;
        unsigned int seconds;
        unsigned int microSeconds;
        std::string stored;
        std::string param;
        std::string server;
        unsigned int port;
        unsigned int serviceMajor;
        unsigned int serviceMinor;
        std::string clientName;
      };


      /** Type define for MaCIServices result table.
       *
       * Type define defining a vector of SMaCIServicesRow elements,
       * essentially forming creating a ResultTable.
       */
      typedef std::vector<SMaCIServicesRow> TMaCIServicesResultTable;


      /** Helper class for handling 'MaCI Service' DB storage format.
       * 
       * This is a helper class for handling 'MaCI Service' storage
       * format over the SQL interface. This storage format is not
       * directly bound to any existing interface, and hence is a good
       * example/starting point for a 'SQL Extension module'
       *
       * \note This helper class is 'Header Only' implementation.
       *
       * \see MaCI::SQL::Ext namespace for more details on helper
       * classes.
       */
      class CMaCIServicesDB : public CSQLExtension
      {
      public:
        /** Constructor.
         *
         * @param[in] aSQLClient Pointer to initialized and connect
         * SQLClient instance. This instance is used for communicating
         * with the SQL interface.
         * @param[in] aTableName Table name to query for.
         */
        CMaCIServicesDB(CSQLClient *aSQLClient, const std::string &aTableName = "services")
          : CSQLExtension(aSQLClient, aTableName) {
        }
        

        /** Destructor.
         */
        ~CMaCIServicesDB(void) {
        }


      private:
        CMaCIServicesDB(const CMaCIServicesDB &) 
          : CSQLExtension(NULL) {}
        CMaCIServicesDB &operator=(const CMaCIServicesDB &) { return *this; }
      };
    }
  }
}
#endif // _MACI_INTERFACE_SQL_EXTENSION_MACISERVICESDB_HPP_
